/*****************************************************************************//*!
* file  : test.c
* creat : apleilx
* data  : 2017/03/02
*******************************************************************************/
#define   osObjectsCreat                                     // define objects in rtxapp module
#include "os_obj.h"                                          // RTOS object definitions
#include "mem_alloc.h"  
#include "sys_task.h"  
#include "bsp_api.h"  

void os_mem_pool_creat(void);

void app_task_start(ULONG thread_input);
void app_task_idle(ULONG thread_input);
void app_task_stat(ULONG thread_input);

void tx_filex_application_define(void);

/*******************************************************************************
* @brief  任务定义
*******************************************************************************/
osThreadDef( task_system, osPriorityHigh, osPriorityHigh, 256 * 4);
osThreadDef( task_console, osPriorityNormal, osPriorityAboveNormal, 256 * 4);
osThreadDef( modbus_task, osPriorityAboveNormal, osPriorityAboveNormal, 256 * 2);
osThreadDef( sd_task, osPriorityBelowNormal, osPriorityAboveNormal, 256 * 8);
osThreadDef( usb_task, osPriorityBelowNormal, osPriorityAboveNormal, 256 * 8);
osThreadDef( lcd_task, osPriorityNormal, osPriorityNormal, 256 * 4);
osThreadDef( nand_task, osPriorityNormal, osPriorityAboveNormal, 256 * 8);
osThreadDef( afat_task, osPriorityNormal, osPriorityAboveNormal, 256 * 10);

/*******************************************************************************
* @brief  任务创建
* \param[in] none
* \retval: none
*******************************************************************************/
int os_thread_init(void)
{
	/**************创建启动任务*********************/
	tx_thread_create(
		&os_obj.tcb_app_task_start,			//task tcb 
		"Task Start",						//task name
		app_task_start,						//task entry
		0,									//task argv
		&os_obj.stk_app_task_start[0],		//task stack
		sizeof(os_obj.stk_app_task_start),	//stack size 
		APP_CFG_TASK_START_PRIO,			//task priority
		APP_CFG_TASK_START_PRIO,			//priority force sw
		TX_NO_TIME_SLICE,					//time slice off
		TX_AUTO_START);						//auto start

	return(0);
}

/*----------------------------------------------------------------------------
 *  creat thread object
 *---------------------------------------------------------------------------*/
int os_thread_creat(void)
{
	os_obj_creat();

	/**************创建状态任务*********************/
	tx_thread_create(&os_obj.tcb_task_stat,	//task tcb  
		"Task STAT",              			//task name
		app_task_stat,                 		//task entry
		0,                           		//task argv
		&os_obj.stk_task_stat[0],			//task stack
		sizeof(os_obj.stk_task_stat),		//stack size 
		APP_CFG_TASK_STAT_PRIO,				//task priority
		APP_CFG_TASK_STAT_PRIO,				//priority force sw
		TX_NO_TIME_SLICE,					//time slice off
		TX_AUTO_START);						//auto start


	/**************创建空闲任务*********************/
	tx_thread_create(&os_obj.tcb_task_idle,	//task tcb  
		"Task Idle",						//task name
		app_task_idle,						//task entry
		0,									//task argv
		&os_obj.stk_task_idle[0],			//task stack
		sizeof(os_obj.stk_task_idle),		//stack size 
		APP_CFG_TASK_IDLE_PRIO,				//task priority
		APP_CFG_TASK_IDLE_PRIO,				//priority force sw
		TX_NO_TIME_SLICE,					//time slice off
		TX_AUTO_START);						//auto start

		
	osThreadCreate(osThread(task_system), "argv");
	osThreadCreate(osThread(task_console), "argv");
	osThreadCreate(osThread(modbus_task), "argv");
	osThreadCreate(osThread(sd_task), "argv");
	osThreadCreate(osThread(usb_task), "argv");
	osThreadCreate(osThread(lcd_task), "argv");
	osThreadCreate(osThread(nand_task), "argv");
	osThreadCreate(osThread(afat_task), "argv");
	
	return 0;
}

/*----------------------------------------------------------------------------
 *  creat os object
 *---------------------------------------------------------------------------*/
int os_obj_creat(void)
{
	/* creat mutex */
	tx_mutex_create(&os_obj.mutex_printf,
		"mutex_printf",
		TX_INHERIT);  //no prio 
	os_obj.mid_printf = &os_obj.mutex_printf;

	tx_mutex_create(&os_obj.mutex_malloc,
		"mutex_malloc",
		TX_INHERIT);  //no prio 
	os_obj.mid_malloc = &os_obj.mutex_malloc;
	
	tx_mutex_create(&os_obj.mutex_file,
		"mutex_file",
		TX_INHERIT);  //no prio 
	os_obj.mid_file = &os_obj.mutex_file;
	
	/* creat quene */
	tx_queue_create(&os_obj.quene_tst,          //Pointer to queue control block
		"tst quene",                			//Pointer to queue name
		1,                          			//Size of each queue message (Number of ULONG)
		os_obj.quene_tst_mem,       			//Starting address of the queue area
		sizeof(os_obj.quene_tst_mem));      	//Number of bytes in the queue
	os_obj.qid_tst = &os_obj.quene_tst;

	/* creat event */
	tx_event_flags_create(&os_obj.event_mb,
		"event mb");
	os_obj.eid_mb = &os_obj.event_mb;

	/* creat semaphore */
	tx_semaphore_create(&os_obj.sem_tst,
		"sem tst",
		1);              //init val  
	os_obj.sid_tst = &os_obj.sem_tst;

	os_mem_pool_creat();
	
	return(0);
}

/*------------------------------------------------------------------------------
 *  task stack used
 *----------------------------------------------------------------------------*/
int32_t os_task_stk_used(osThreadId tid)
{
	uint32_t start,end, unused;
	
	start = (uint32_t)tid->tx_thread_stack_start;
	end = (uint32_t)tid->tx_thread_stack_end;
	
	unused = start;
	
	while(inpw(unused) == 0xEFEFEFEF && inpw(unused+4) == 0xEFEFEFEF)
	{
		unused += 8;
	}
	
	return ((end+1) - unused);
}


void os_task_info(void)
{
	extern TX_THREAD *_tx_thread_created_ptr;
	TX_THREAD *tid = _tx_thread_created_ptr;

    dbg_print("===========================================================\n");
    dbg_print("===========================================================\n");
	dbg_print("system stack used : %d %%\n", stack_used()/10);	
	dbg_print("system heap used : %d %%\n", mem_sram.api->perused() /10);
	dbg_print("system ccm used : %d %%\n", mem_ccm.api->perused()/10);
	
	do
	{
		int32_t stk_used = os_task_stk_used(tid);
		
		dbg_print("prio: %-3d, preempt: %-3d, run count: %-8d :: stack (%08x - %08x), " \
				  "size %5d, used %5d # %-3d%% :: %s\n",
			tid->tx_thread_priority,
			tid->tx_thread_preempt_threshold,
			tid->tx_thread_run_count,
			tid->tx_thread_stack_start,
			tid->tx_thread_stack_end,
			tid->tx_thread_stack_size,
			stk_used,
			stk_used * 100 / tid->tx_thread_stack_size,
			tid->tx_thread_name);

		tid = tid->tx_thread_created_next;
	} while (tid && tid != _tx_thread_created_ptr);
}
